home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / WSNAKE.ZIP / SNAKE / SNAKE.CPP < prev    next >
C/C++ Source or Header  |  1996-04-29  |  8KB  |  402 lines

  1. // the Snake
  2. // Copyright (c)1996 Fredrik Wangel (WaF)
  3. //
  4.  
  5. #include <dos.h>
  6. #include <conio.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #include <ctype.h>
  12. #include "snake.h"
  13.  
  14. void waitretrace(void);
  15. void waitdisplay(void);
  16. int  keyhit(void);
  17. void flushkbd(void);
  18. void setborderc(byte color);
  19. void show_display(void);
  20. void hide_display(void);
  21. void draw_score(void);
  22. void fade_to_black(byte start, byte stop, byte steps);
  23. void fade_to_color(byte start, byte stop, byte steps);
  24.  
  25. #define TRUE  '-'/'-'
  26. #define FALSE '-'-'-'
  27.  
  28. #define KEY_SOUND 'S'
  29. #define KEY_ESC   27
  30.  
  31. #define KEY_UP    72
  32. #define KEY_DOWN  80
  33. #define KEY_LEFT  75
  34. #define KEY_RIGHT 77
  35.  
  36. #define SCRSX  80
  37. #define XSIZE  80
  38. #define YSIZE  40
  39. #define BLOCKS 20
  40. #define LX2POS 44
  41. #define LXPOS   1
  42. #define LYPOS  YSIZE + 2
  43. #define GP     ((YSIZE * BLOCKS) / XSIZE)    // Base points
  44.  
  45. #define ADDSNAKE   15 // random(x) at increase
  46. #define LOOSESNAKE  4 // and decrease respectively
  47. #define BEGINSNAKE  2 // starting length of the snake
  48. #define FROGAMOUNT  5 // number of frogs
  49.  
  50. #define HI(a) (a & 0xff00) / 0x100
  51. #define LO(a) (a & 0x00ff)
  52. #define FOREVER for(;;)
  53.  
  54. byte key, firsttime = 1, ljud = 1;
  55. byte grid[XSIZE][YSIZE];
  56. byte frx[FROGAMOUNT], fry[FROGAMOUNT];
  57. int  snx[1500], sny[1500];
  58. int  length, head, tail;
  59. int  grow, decline, frogtime[FROGAMOUNT];
  60. int  millifemtio, tid;
  61. long score;
  62. long bestscore = 0;
  63. int  besttid = 0, bestlength = 0;
  64.  
  65. const word Clear = 0x2000 + byte(' ');
  66. const word Frog  = 0x2A00 + byte('Ω');
  67. const word Snake = 0x2C00 + byte('@');
  68. const word Brick = 0x2600 + byte('≡');
  69. const word Block = 0x2F00 + byte('█');
  70.  
  71. void save_palette()
  72. {
  73.     for(word i = 0; i < 64; i++)
  74.         getpalrgb(i, pal_orig[i].r, pal_orig[i].g, pal_orig[i].b);
  75. }
  76.  
  77. void restore_palette()
  78. {
  79.     for(word i = 0; i < 64; i++)
  80.         setpalrgb(i, pal_orig[i].r, pal_orig[i].g, pal_orig[i].b);
  81. }
  82.  
  83. void clear_palette()
  84. {
  85.     for(word i = 0; i < 64; i++)
  86.     {
  87.         pal[i].r = 0;
  88.         pal[i].g = 0;
  89.         pal[i].b = 0;
  90.         setpalrgb(i, 0, 0, 0);
  91.     }
  92. }
  93. void waitforkey(void)
  94. {
  95.     gotoxy(LXPOS, LYPOS + 2);
  96.     printf("** Press any key to begin **");
  97.     clreol();
  98.     printf("\r");
  99.     flushkbd();
  100.     while(!keyhit());
  101.     clreol();
  102. }
  103.  
  104. void notify(void)
  105. {
  106.     if(ljud)
  107.     {
  108.         buzz(2500); delay(25);
  109.         buzz(1500); delay(25); buzz(750); delay(50);
  110.         buzz(1000); delay(100); quiet();
  111.     }
  112.     draw_score();
  113.     gotoxy(LXPOS, LYPOS + 1);
  114.     printf("You played for %04d sec.", tid);
  115.     clreol();
  116.     delay(500);
  117. }
  118.  
  119. void put_block(word x, word y, word item)
  120. {
  121.     asm {
  122.         mov   ax, 0xb800
  123.         mov   es, ax
  124.         mov   ax, y
  125.         mov   dl, SCRSX
  126.         shl   dl, 1
  127.         mul   dl
  128.         mov   dx, x
  129.         shl   dx, 1
  130.         add   ax, dx
  131.         mov   di, ax
  132.         mov   ax, item
  133.         mov   [es:di], ax
  134.     }
  135. }
  136.  
  137. void set_point(word x, word y, word item)
  138. {
  139.     put_block(x, y, item);
  140.     grid[x][y] = HI(item);
  141. }
  142.  
  143. void clear_grid(void)
  144. {
  145.     word x, y;
  146.  
  147.     hide_display();
  148.     for(x=0; x < XSIZE; x++)
  149.     {
  150.         for(y=0; y < YSIZE; y++)
  151.             if(grid[x][y] != HI(Clear))
  152.                 set_point(x, y, Clear);
  153.         set_point(x, YSIZE - 1, Block);
  154.         set_point(x, 0, Block);
  155.     }
  156.     for(y=0; y < YSIZE; y++)
  157.     {
  158.         set_point(XSIZE - 1, y, Block);
  159.         set_point(0, y, Block);
  160.     }
  161.     for(x=0; x < BLOCKS; x++)
  162.         set_point(random(XSIZE - 1) + 1, random(YSIZE - 1) + 1, Block);
  163.     show_display();
  164. }
  165.  
  166. void draw_score(void)
  167. {
  168.     gotoxy(LXPOS, LYPOS);
  169.     printf("Length: %04d  Points: %010ld\r", length, score);
  170.     if((score > bestscore) || (length > bestlength))
  171.     {
  172.         if(score > bestscore)
  173.             bestscore = score;
  174.         else
  175.             bestlength = length;
  176.         gotoxy(LX2POS, LYPOS);
  177.         printf("Longest: %04d  Highscore: %010ld\r", bestlength, bestscore);
  178. //        printf("Longest: %04d  Highscore: %010ld\r", bestlength, bestscore);
  179.     }
  180. }
  181.  
  182. void create_frog(int n)
  183. {
  184.     word x, y;
  185.     do
  186.     {
  187.         x = random(XSIZE - 1) + 1;
  188.         y = random(YSIZE - 1) + 1;
  189.     }
  190.     while (grid[x][y] != HI(Clear));
  191.     frx[n] = x;
  192.     fry[n] = y;
  193.     set_point(x, y, Frog);
  194.     frogtime[n] = 20 + random(50);
  195.     if(ljud)
  196.     {
  197.         buzz(50); delay(5); quiet();
  198.     }
  199. }
  200.  
  201. void check_frogs(void)
  202. {
  203.     word n, x, y;
  204.     for(n=0; n < FROGAMOUNT; n++)
  205.         if(!frogtime[n]--)
  206.         {
  207.             x = frx[n];
  208.             y = fry[n];
  209.             create_frog(n);
  210.             set_point(x, y, random(10)?Clear:Brick);
  211.         }
  212. }
  213.  
  214. void replace_frog(word x, word y)
  215. {
  216.     word n;
  217.     for(n=0; n < FROGAMOUNT; n++)
  218.         if(frx[n] == x && fry[n] == y)
  219.             create_frog(n);
  220.     set_point(x, y, Clear);
  221. }
  222.  
  223. void setup_game(void)
  224. {
  225.     clear_grid();
  226.     score = 0;
  227.     millifemtio = 0;
  228.     tid = 0;
  229.     length = 1;
  230.     grow = BEGINSNAKE - 1;
  231.     decline = 0;
  232.     head = tail = 0;
  233.     snx[0] = XSIZE / 2;
  234.     sny[0] = YSIZE / 2;
  235.     set_point(snx[0], sny[0], Snake);
  236.     key = KEY_RIGHT;
  237.     for(word i=0; i < FROGAMOUNT; i++)
  238.         create_frog(i);
  239.     if(firsttime)
  240.     {
  241.         firsttime = 0;
  242.         fade_to_color();
  243.     }
  244.     waitforkey();
  245.     draw_score();
  246.     gotoxy(LXPOS, LYPOS + 1);
  247.     clreol();
  248. }
  249.  
  250. bool play_one_game(void)
  251. {
  252.     byte item;
  253.     int nx, ny;
  254.     byte code;
  255.  
  256.     gotoxy(LX2POS, LYPOS);
  257.     printf("Longest: %04d  Highscore: %010ld\r", bestlength, bestscore);
  258.     gotoxy(LX2POS, LYPOS + 1);
  259.     printf("Best Time: %04d\r", besttid);
  260.     FOREVER
  261.     {
  262.         waitretrace();
  263.         delay(50);
  264.         millifemtio++;
  265.         if(!(millifemtio % 20))
  266.         {
  267.             millifemtio = 0;
  268.             tid++;
  269.             gotoxy(LXPOS, LYPOS + 1);
  270.             printf("Time: %04d\r", tid);
  271.             if(tid > besttid)
  272.             {
  273.                 besttid = tid;
  274.                 gotoxy(LX2POS, LYPOS + 1);
  275.                 printf("Best Time: %04d\r", besttid);
  276.             }
  277.         }
  278.         if(keyhit())
  279.         {
  280.             code = getch();
  281.             if(code == 0)
  282.             {
  283.                 code = getch();
  284.                 switch(code)
  285.                 {
  286.                     case KEY_UP    :
  287.                     case KEY_DOWN  :
  288.                     case KEY_LEFT  :
  289.                     case KEY_RIGHT : key = code; break;
  290.                 }
  291.             }
  292.             else
  293.                 switch(toupper(code))
  294.                 {
  295.                     case KEY_ESC   :    return TRUE;
  296.                     case KEY_SOUND :    ljud = 1 - ljud;
  297.                                             setborderc(ljud * 12);
  298.                                             break;
  299.                 }
  300.         }
  301.         nx = snx[head];
  302.         ny = sny[head];
  303.         switch(key)
  304.         {
  305.             case KEY_UP    : ny -= 1; break;
  306.             case KEY_DOWN  : ny += 1; break;
  307.             case KEY_LEFT  : nx -= 1; break;
  308.             case KEY_RIGHT : nx += 1; break;
  309.         }
  310.         item = grid[nx][ny];
  311.         switch(item)
  312.         {
  313.             case HI(Block) :  return FALSE;
  314.             case HI(Frog)  :  grow += 2 + random(ADDSNAKE);
  315.                                     score += GP * (length + grow) * (1 + (tid * tid) / 300);
  316.                                     replace_frog(nx, ny);
  317.                                     if(ljud)
  318.                                     {
  319.                                         buzz(250); delay(10); buzz(500); delay(10); quiet();
  320.                            }
  321.             case HI(Clear) :  head = (head + 1) % 1500;
  322.                                     snx[head] = nx;
  323.                                     sny[head] = ny;
  324.                                     set_point(nx, ny, Snake);
  325.                                     if(decline)
  326.                                     {
  327.                                         decline--;
  328.                                         length--;
  329.                                         if(length < 1)
  330.                                             return FALSE;
  331.                                         draw_score();
  332.                                         if(ljud)
  333.                                         {
  334.                                             buzz(1500); delay(5); quiet();
  335.                                         }
  336.                                         set_point(snx[tail], sny[tail], Clear);
  337.                                         tail = (tail + 1) % 1500;
  338.                                     }
  339.                                     if(grow)
  340.                                     {
  341.                                         grow--;
  342.                                         length++;
  343.                                         draw_score();
  344.                                     }
  345.                                     else
  346.                                     {
  347.                                         set_point(snx[tail], sny[tail], Clear);
  348.                                         tail = (tail + 1) % 1500;
  349.                                     }
  350.                                     break;
  351.             case HI(Brick) :  decline += 1 + random(LOOSESNAKE);
  352.                                     set_point(nx, ny, Clear);
  353.                                     break;
  354.             case HI(Snake) :  return FALSE;
  355.         }
  356.         check_frogs();
  357.     }
  358. }
  359.  
  360. void play_game(void)
  361. {
  362.     FOREVER
  363.     {
  364.         setup_game();
  365.         if(play_one_game())
  366.             return;
  367.         notify();
  368.     }
  369. }
  370.  
  371. void set_up(void)
  372. {
  373.     randomize();
  374.     textmode(C4350);
  375.     clrscr();
  376. }
  377.  
  378. void clean_up(void)
  379. {
  380.     textmode(C80);
  381.     printf("the Snake (c)1996 Fredrik Wangel (WaF)\r\n");
  382.     flushkbd();
  383. }
  384.  
  385. int main(void)
  386. {
  387.     save_palette();
  388.     fade_to_black();
  389.     set_up();
  390.     setborderc(12);
  391.     play_game();
  392.     setborderc(0);
  393.     fade_to_black();
  394.     hide_display();
  395.     clean_up();
  396.     clear_palette();
  397.     show_display();
  398.     fade_to_color();
  399.     restore_palette();
  400.     return 0;
  401. }
  402.